//
//  SocketManager.m
//  emyone
//
//  Created by LiangLigeng on 13-12-9.
//  Copyright (c) 2013年 LiangLigeng. All rights reserved.
//

#import "SocketManager.h"
#import "JSONKit.h" 

static SocketManager *singleton=nil;

@implementation SocketManager

+(SocketManager *)shareInstance{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton=[[SocketManager alloc] init];
        
        //[[NSUserDefaults standardUserDefaults]setObject:[[NSUserDefaults standardUserDefaults]objectForKey:EMY_USER_ID] forKey:emyID];
        //[[NSUserDefaults standardUserDefaults]setObject:[[NSUserDefaults standardUserDefaults]objectForKey:EMY_USER_PASSWORD] forKey:emyPassword];
        //[[NSUserDefaults standardUserDefaults]synchronize];
        [singleton setToken];
        
        //NSLog(@"%@",loginSrting);
        [singleton setupSocket];
        
    });
    return singleton;
}

-(void)setToken{
    NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
    _token=[defaults objectForKey:@"DeviceToken"];
    //NSString *loginSrting=[@"{\"command\":\"LOGIN\",\"access_token\":\"" stringByAppendingString:token];
    //loginSrting=[loginSrting stringByAppendingString:@"\"}"];
}

//
- (void)setupSocket
{
    // Setup our socket (GCDAsyncSocket).
	// The socket will invoke our delegate methods using the usual delegate paradigm.
	// However, it will invoke the delegate methods on a specified GCD delegate dispatch queue.
	//
	// Now we can configure the delegate dispatch queue however we want.
	// We could use a dedicated dispatch queue for easy parallelization.
	// Or we could simply use the dispatch queue for the main thread.
	//
	// The best approach for your application will depend upon convenience, requirements and performance.
	//
	// For this simple example, we're just going to use the main thread.
	
	dispatch_queue_t mainQueue = dispatch_get_main_queue();
	
	_asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];
#if USE_SECURE_CONNECTION
	{
		NSString *host = SOCKET_HOST;
		uint16_t port = PORT;
		
		//DDLogInfo(@"Connecting to \"%@\" on port %hu...", host, port);
		//self.viewController.label.text = @"Connecting...";
		
		NSError *error = nil;
		if (![asyncSocket connectToHost:host onPort:port error:&error])
		{
			NSLog(@"Error connecting: %@", error);
			//self.viewController.label.text = @"Oops";
		}else{
            //[asyncSocket readDataToLength:LENGTH_HEADER withTimeout:-1 tag:TAG_HEADER];
        }
	}
#else
	{
		NSString *host = SOCKET_HOST;
		uint16_t port = PORT;
		
		NSError *error = nil;
        //[[NSNotificationCenter defaultCenter]postNotificationName:@"connect" object:@"连接中..."];
		if (![_asyncSocket connectToHost:host onPort:port error:&error])
		{
            //[[NSNotificationCenter defaultCenter]postNotificationName:@"connect" object:@"易麦(未连接)"];
            
            NSLog(@"Error connecting: %@", error);
			//self.viewController.label.text = @"Oops";
		}
        
		// You can also specify an optional connect timeout.
		
        //	NSError *error = nil;
        //	if (![asyncSocket connectToHost:host onPort:80 withTimeout:5.0 error:&error])
        //	{
        //		DDLogError(@"Error connecting: %@", error);
        //	}
		
	}
#endif
}

//发送消息
-(void)sendMsg:(NSString *) msgString{
    //int32_t headerLength=[self calc_charsetNum:msgString];
    //headerLength=htonl(headerLength);
    //NSData *headerLen=[NSData dataWithBytes:&headerLength length:4];
    //[headerLen retain];
    //[_asyncSocket writeData:headerLen withTimeout:-1 tag:TAG_HEADER];
    NSData *body=[[msgString stringByAppendingString:@"\n" ] dataUsingEncoding:NSUTF8StringEncoding];
    //[body retain];
    [_asyncSocket writeData:body withTimeout:-1 tag:TAG_BODY];
    NSLog(@"writed........");
}

//计算utf8编码下的长度
- (int)calc_charsetNum:(NSString*)_str
{
    unsigned result = 0;
    const char *tchar=[_str UTF8String];
    if (NULL == tchar) {
        return result;
    }
    result = strlen(tchar);
    return result;
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Socket Delegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//连接成功后的回调函数
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
	//[[NSNotificationCenter defaultCenter]postNotificationName:@"connect" object:@"易麦"];
    //_status = SocketConnectionStatusConnected;
    //if ([self respondsToSelector:@selector(socketConnectionDidConnectedToServer:)]) {
    //    [self socketConnectionDidConnectedToServer:self];
    //}
    //已经连接上之后，开始读取data，调用下面的readDataToLength:withTimeout:tag:方法，在此方法中会调用到socket的代理方法： socket：didReadData：tag：方法。
    //[_asyncSocket readDataToLength:LENGTH_HEADER withTimeout:-1 tag:TAG_HEADER];
    NSString *sp=@"\n";
    [_asyncSocket readDataToData:[sp dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
    NSLog(@"socket:%p didConnectToHost:%@ port:%hu", sock, host, port);    
    //[self sendMsg:@"test"];
    NSString *device_token=[[NSUserDefaults standardUserDefaults]objectForKey:@"DeviceToken"];
    NSLog(@"device_token:%@",device_token);
    NSDictionary *loginDic=[NSDictionary dictionaryWithObjectsAndKeys:
                          @"LOGIN",@"command",
                          device_token,@"device_id",
                          @"1",@"os",
                          [UIDevice currentDevice].systemVersion ,@"os_version",
                          @"1.0.1",@"app_version",nil];
    
    NSString *loginSrting=[loginDic JSONString];
    [self sendMsg:loginSrting];
    
    
    
#if USE_SECURE_CONNECTION
	{
		// Connected to secure server (HTTPS)
        
#if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR
		{
			// Backgrounding doesn't seem to be supported on the simulator yet
			
			[sock performBlock:^{
				if ([sock enableBackgroundingOnSocket])
					NSLog(@"Enabled backgrounding on socket");
				else
					NSLog(@"Enabling backgrounding failed!");
			}];
		}
#endif
		
		// Configure SSL/TLS settings
		NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3];
		
		// If you simply want to ensure that the remote host's certificate is valid,
		// then you can use an empty dictionary.
		
		// If you know the name of the remote host, then you should specify the name here.
		//
		// NOTE:
		// You should understand the security implications if you do not specify the peer name.
		// Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion.
		
		[settings setObject:@"mina.emyone.com"
					 forKey:(NSString *)kCFStreamSSLPeerName];
		
		// To connect to a test server, with a self-signed certificate, use settings similar to this:
		
        //	// Allow expired certificates
        //	[settings setObject:[NSNumber numberWithBool:YES]
        //				 forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
        //
        //	// Allow self-signed certificates
        //	[settings setObject:[NSNumber numberWithBool:YES]
        //				 forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
        //
        //	// In fact, don't even validate the certificate chain
        //	[settings setObject:[NSNumber numberWithBool:NO]
        //				 forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
		
		NSLog(@"Starting TLS with settings:\n%@", settings);
		
		[sock startTLS:settings];
		
		// You can also pass nil to the startTLS method, which is the same as passing an empty dictionary.
		// Again, you should understand the security implications of doing so.
		// Please see the documentation for the startTLS method in GCDAsyncSocket.h for a full discussion.
		
	}
#else
	{
		// Connected to normal server (HTTP)
		
#if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR
		{
			// Backgrounding doesn't seem to be supported on the simulator yet
			
			[sock performBlock:^{
				if ([sock enableBackgroundingOnSocket])
					NSLog(@"Enabled backgrounding on socket");
				else
					NSLog(@"Enabling backgrounding failed!");
			}];
		}
#endif
	}
#endif
}

- (void)socketDidSecure:(GCDAsyncSocket *)sock
{
	NSLog(@"socketDidSecure:%p", sock);
	//self.viewController.label.text = @"Connected + Secure";
	
	NSString *requestStr = [NSString stringWithFormat:@"GET / HTTP/1.1\r\nHost: %@\r\n\r\n", @"mina.emyone.com"];
	NSData *requestData = [requestStr dataUsingEncoding:NSUTF8StringEncoding];
	
	[sock writeData:requestData withTimeout:-1 tag:0];
	[sock readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
   
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
	NSLog(@"socket:%p didWriteDataWithTag:%ld", sock, tag);
}

//- (void)socket:(GCDAsyncSocket *)sock readDataToData:msgSeparator withTimeout:TIMEOUT_NONE tag:TAG_CAPABILITIES

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    if ([self respondsToSelector:@selector(socketConnection:didReceivedData:)]) {
        [self socketConnection:self.asyncSocket didReceivedData:data];
    }
    //NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
    //NSString *sp=@"\r\n";
    NSString *sp=@"\n";
    [_asyncSocket readDataToData:[sp dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:1];
}

- (void)socketConnection:(GCDAsyncSocket *)sock didReceivedData:(NSData *)data
{
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    id result= [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    NSDictionary *jsonDictionary = (NSDictionary *)result;
    NSString *command=[jsonDictionary objectForKey:@"command"];
    int isSuccess=[[jsonDictionary objectForKey:@"success"]intValue];
    if(command!=nil&&[command isEqualToString:@"connect"]){
        if (isSuccess) {
            [self heartBeat];
        }else{
            
        }
        //NSLog(@"login:%d",isSuccess);
    }
    if (command!=nil&&[command isEqualToString:@"push"]) {
        NSLog(@"%@",@"tuisong");
        NSString *title=[jsonDictionary objectForKey:@"title"];
        //发送全局通知
        [[NSNotificationCenter defaultCenter]postNotificationName:@"newpush" object:title];
    }
    NSLog(@"data:%@",dataString);
}
//心跳包
-(void)heartBeat{
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue , ^{ @autoreleasepool {
        _heartbeat=[NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(OnHeartBeat) userInfo:nil repeats:YES];
        [_heartbeat fire];
    }});
   
}
-(void)OnHeartBeat{
    [self sendMsg:@"HEARTBEATREQUEST"];
}


//断开连接后的回调代理函数
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    [[NSNotificationCenter defaultCenter]postNotificationName:@"connect" object:@"易麦(未连接)"];
    [_heartbeat invalidate];
	NSLog(@"socketDidDisconnect:%p withError: %@", sock, err);
    if (![_reconnect isValid]) {
        [self socketReconnect];
    }
	//self.viewController.label.text = @"Disconnected";`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
}

//重连
-(void)socketReconnect
{
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue , ^{ @autoreleasepool {
        _reconnect=[NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(OnReconnect) userInfo:nil repeats:YES];
        [_reconnect fire];
    }});
}
-(void)OnReconnect
{
    if (!self.asyncSocket.isConnected) {
        NSString *host = SOCKET_HOST;
		uint16_t port = PORT;
        NSError *error = nil;
		if (![_asyncSocket connectToHost:host onPort:port error:&error])
		{
            
		}
        //[self setupSocket];
    }else{
        [_reconnect invalidate];
    }
}

@end
